透過網頁 input 或 url,在送資料的時候帶 SQL query 去操作資料庫,可以是新增、刪除或其他操作。
簡單來說,就是對輸入的 request 做檢查,把 SQL query 過濾掉。
實作上,PHP 可以透過 PDO 來相對容易做到。
PDO—PHP Data Objects—are a database access layer providing a uniform method of access to multiple databases.
使用 PDO 有兩階段:
Using prepared statements will help protect you from SQL injection.
透過在準備階段使用 placeholder 去過濾 SQL 達到預防 SQL injection 的效果。
# 有 SQL Injection 風險
$query = $DB->prepare("INSERT INTO users (name, email) values ($name, $email)");
# unnamed placeholders
$query = $DB->prepare("INSERT INTO users (name, email) values (?, ?)");
# named placeholders
$query = $DB->prepare("INSERT INTO users (name, email) values (:name, :email)");
bind 是綁定參數到 placeholder
Object-Relational Mapping
將關連式資料庫的資料映射到物件,好讓我們能用物件導向的邏輯去存取資料庫資料;目前大部分框架都有搭配各自的 ORM,Laravel 搭配的是 Eloquent ORM、Django 搭配的是 Django ORM。
而 Eloquent ORM 基本上是建構在 PDO 之上的,所以使用得當的話是預防 SQL Injection 的。
值得注意的是,還是有一些方法是會有漏洞的,例如 whereRaw()
。有 raw 的基本上就是不會去做 SQL 的過濾;使用時就要記得用 placeholder,就是寫那個「?」,而非直接把變數接在 SQL 裡。
// Dont Do
$users = User::whereRaw('age > ? and votes = 100', [25])->get();
// Do
$users = User::whereRaw("age > {$_GET['age']} and votes = 100")->get();